package com.java.fileman;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;


/**
 * Servlet implementation class FileServerServlet
 */
public class FileServerServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#HttpServlet()
     */
    String currentDir = "";
    Logger log;
    public static Properties prop = new Properties();

    public FileServerServlet() {
        super();
        // TODO Auto-generated constructor stub
        log = Logger.getLogger(FileServerServlet.class);
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     * response)
     */
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub

        AuthToken authToken = AuthServlet.getAuthToken(request);
        if (authToken == null || authToken.getUsername().equals("")) {
            log.debug("auth token is not set");
            response.sendRedirect("login.jsp");
            return;
        }
        
        
        
        try {
            prop.load(new FileInputStream(getAppDir() + "WEB-INF" + File.separator + "config.properties"));
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return;
        }
        log.debug("current dir : " + getCurrentDir(request));
        try {
            currentDir = getCurrentDir(request);
            try {
                String fid = request.getParameter("f");
                if(!FileObject.getAccessObject().checckAccess(authToken.getGroup(), fid)){
                    return;
                }else{
                    log.debug("access for "+fid+" not allowed for "+authToken.getUsername());
                }
                File getFile = new File(getCurrentDir(request) + File.separator
                        + fid);
                log.debug("requested resource : " + getFile.getPath());
                if (getFile.exists() && getFile.isFile()
                        && !getFile.getName().equals("..")) {
                    // do download code here
                    log.debug("file download starts : " + getFile.getPath());
                    File f = new File(getCurrentDir(request) + File.separator
                            + getFile.getName());
                    int length = 0;
                    ServletOutputStream op = response.getOutputStream();
                    ServletContext context = getServletConfig().getServletContext();
                    String mimetype = context.getMimeType(f.getPath());

                    response.setContentType((mimetype != null) ? mimetype
                            : "application/octet-stream");
                    response.setContentLength((int) f.length());
                    response.setHeader("Content-Disposition",
                            "attachment; filename=\"" + getFile.getName()
                            + "\"");

                    byte[] bbuf = new byte[1024];
                    DataInputStream in = new DataInputStream(
                            new FileInputStream(f));

                    while ((in != null) && ((length = in.read(bbuf)) != -1)) {
                        op.write(bbuf, 0, length);
                    }
                    in.close();
                    op.flush();
                    op.close();

                } else if (getFile.exists() && !getFile.isFile()) {
                    setCurrentDir(request, getFile.getName());
                }
            } catch (NullPointerException e) {
                // e.printStackTrace();
            }
            File file = new File(getCurrentDir(request));
            String[] files = file.list();
            HashMap<String, FileObject> map = new HashMap<String, FileObject>();

            for (int i = 0; i < files.length; i++) {
                FileObject fileObject = new FileObject(getCurrentDir(request)
                        + File.separator + files[i]);
                if (files[i].equals(AccessObject.FILE)) {
                    FileObject.setAccessObject(new AccessObject(getCurrentDir(request)
                            + File.separator + AccessObject.FILE));
                    System.out.println(fileObject.getAccessObject());
                } else {
                    map.put(files[i], fileObject);
                }
            }

            // sorting the map
            List<FileObject> newMap = new ArrayList<FileObject>(map.values());
            Collections.sort(newMap, new Comparator<FileObject>() {
                public int compare(FileObject o1, FileObject o2) {
                    return o1.getType() - o2.getType();
                }
            });

            request.setAttribute("userInfo", AuthServlet.getAuthToken(request));
            request.setAttribute("files", newMap);
            getServletConfig().getServletContext().getRequestDispatcher("/list.jsp").forward(request, response);

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private String getCurrentDir(HttpServletRequest request) {

        HttpSession session = request.getSession();
        String currentDir;
        if (session.getAttribute("currentDir") != null
                && !session.getAttribute("currentDir").equals("")) {
            currentDir = (String) session.getAttribute("currentDir");
        } else {
            currentDir = prop.getProperty("base.dir");
        }
        log.debug("getCurrentDir()=" + currentDir);
        return currentDir;
    }

    private void setCurrentDir(HttpServletRequest request, String append) {
        HttpSession session = request.getSession();
        if (append != null && !append.equals("..") && !append.equals("")) {
            String cd = getCurrentDir(request);
            cd = cd + File.separator + append;
            session.putValue("currentDir", cd);
        } else if (append != null && append.equals("..")) {

            String cd = getCurrentDir(request);
            if (cd.length() > prop.getProperty("base.dir").length()) {
                cd = cd.substring(0, cd.lastIndexOf(File.separator));
                session.putValue("currentDir", cd);
            }
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     * response)
     */
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

    public String getAppDir() {
        String path = this.getServletContext().getRealPath(File.separator);
        log.debug("Application directory  :  " + path);
        return path;
    }
}
